//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#ifndef __GRAFIX_SURFACECACHE_H__
#define __GRAFIX_SURFACECACHE_H__

#include <engine.h>

class BufferCache;

class Buffer
{
public:
    GrafixAttribute attribute;

    Int32 size;

    BitmapBufInfo info;
};

class BufferCacheNode : public DLinkNode
{
public:
    BufferCacheNode() {
        Initialize();
        m_surface = NULL;
        m_cache = NULL;
        m_mapped = FALSE;
        m_mapAddress = 0;
        m_processId = 0;

#ifdef _DEBUG
        m_free = FALSE;
#endif
    }

    BufferCacheNode(
        /* [in] */ BufferCache* cache,
        /* [in] */ CGrafixSurface* surface) {
        Initialize();
        m_surface = surface;
        m_cache = cache;
        m_mapped = FALSE;
        m_mapAddress = 0;
        m_processId = 0;

#ifdef _DEBUG
        m_free = FALSE;
#endif
    }

    ECode Resize(
        /* [in] */ Int32 width,
        /* [in] */ Int32 height);

    ECode Map(
        /* [in] */ Int32 x,
        /* [in] */ Int32 y,
        /* [in] */ Int32 width,
        /* [in] */ Int32 height,
        /* [out] */ BitmapBufInfo* addr);

    ECode Unmap();

    Void Lock() {
        m_lock.Lock();
    }

    Void Unlock() {
        m_lock.Unlock();
    }

    Int32 AddRef() {
        Int32 ref = m_reference.Increment();
        assert(ref >= 1);

        GFX_EXPRESSION(DEBUG_BUFFERREF,
            kprintf("Buffer Node 0x%08x after AddRef reference = %d\n",
            this, ref));

        return ref;
    }

    Int32 Release();

public:
    VinciLock m_lock;

    CGrafixSurface* m_surface;

    // The parent.
    //
    BufferCache* m_cache;

    // The space.
    //
    Buffer m_buffer;

    // reference.
    //
    Interlocked m_reference;

    // Just for the map.
    //
    Boolean m_mapped;
    Interlocked m_mapCount;
    Address m_mapAddress;
    Int32 m_processId;

#ifdef _DEBUG
    Boolean m_free;
#endif
};

class BufferCache
{
public:
    ECode GetBufferNode(
        /* [in] */ CGrafixSurface* surface,
        /* [in] */ Int32 width,
        /* [in] */ Int32 height,
        /* [in] */ GrafixAttribute attribute,
        /* [in] */ PixelFormat format,
        /* [out] */ BufferCacheNode** buffer);

    ECode TakeBackBufferNode (
        /* [in] */ BufferCacheNode* buffer);

    Void Destroy();

    Void Lock() {
        m_lock.Lock();
    }

    Void Unlock() {
        m_lock.Unlock();
    }

    Void Dump();
public:
    // Using buffer.
    //
    BufferCacheNode m_availabilityHeader;

    // Unusing buffer.
    //
    BufferCacheNode m_invalidHeader;

    VinciLock m_lock;
};

#endif // __GRAFIX_SURFACECACHE_H__

